/**
 *上海交大-鹏越惊虹
 */

package org.infosec.lc.exercises;

/**
 * @Title: NumberConvert.java
 * @Package org.infosec.lc.exercises.NumberConvert
 * @Description: TODO
 * @author 林超
 * @date Apr 23, 2013 10:48:47 AM
 * @version V1.0
 * 
 *          在继续之前，来温故一点基础（为简单起见，只说整数）。
 *          1、做基本运算（如+、-、*、/、<<、>>、>>>、~、^等），当两个操作数的类型是byte
 *          ，short，char，int之一的时候，结果的类型是int； 2、做整数基本运算时，当一个操作数是long，结果是long；
 *          3、不加任何修饰的整数字面值默认就是int类型。
 * 
 *          下面对上面的几点举例说明： short s1 = 1;//OK short s2 = s1 + 1;//ERROR
 * 
 * 
 *          上面的第一句1整形字面值，它的类型是int，为什么可以直接赋值给short呢？因为字面值都是常量，
 *          编译器能很容易的检测出它到底在不在short所能表示的值的范围内。当写成short s1 =
 *          32768的时候，编译就知道short容不下32768了，就会报错。
 *          而对于第二句，s1是short类型，1是int类型，结果是int类型
 *          ，自然不能自动赋值给short类型的s2了，因为有潜在的高位有效值被截断的风险
 *          。可能会有人想，上面s1已经赋值了一个字面值，对于下面的s2
 *          ，编译器应该也可以计算出它的值啊。如果s1是final的，确实会这样，但s1是变量
 *          ，编译器是无法预测它会不会在运行期改变的，即使它可能不会改变。
 * 
 *          再来一个，计算一年有多少毫秒，粗心的人可能这么写： long mills = 365 * 24 * 60 * 60 * 1000;
 * 
 *          明眼人一看就有问题了，后面的几个数字都是int类型，计算后结果还是int类型，再将其转换成long类型，等效于以下的逻辑： int
 *          tmp = 365 * 24 * 60 * 60 * 1000; long mills = tmp;
 * 
 *          出计算结果的时候数据已经溢出了，再将其转换成long，依然得不到正确的结果，这样的计算很常见，也很容易被人疏忽，纠正它很容易，
 *          只要指定一个数为long类型即可： long mills = 365 * 24 * 60 * 60 * 1000L;
 * 
 *          开始简短的正题，如下的两段代码的区别： short s = 1; s = s + 1;//error short s = 1; s +=
 *          1;//ok
 * 
 *          第一段代码上面已经有分析了，它通不过编译；来看看第二段，首先它能通过编译，来看看编译后的字节码（javap -c 类名）是什么样的吧：
 * 
 *          0: iconst_1 1: istore_1 2: iload_1 3: iconst_1 4: iadd 5: i2s 6:
 *          istore_1
 * 
 *          指令0,1做了short s =
 *          1操作，指令2,3,4做了s+1的操作，第5条是关键，做了一个强制转换，将int转换为short，第6条将强制转换的结果存回变量s。
 * 
 *          如果s是int类型呢？ int s = 1; s += 1;//ok
 * 
 *          对应的字节码：
 * 
 *          0: iconst_1 1: istore_1 2: iinc 1, 1
 * 
 *          它直接等价于i++操作了，和以下代码生成的字节码是一样的： int s = 1; s++;
 * 
 *          当s += 2的时候，指令为iinc 1, 2，这里是没有强制转换的。
 * 
 *          综上可以看到（其中type为byte，short，char，int之一，value可为变量可为常量，类型可为byte，short，
 *          char，int，float，double，long）: type s = value; s += ovalue;//ok
 * 
 *          逻辑上等价于（说逻辑上是因为type为int的时候并不存在强制转换，但结果是相同的）： type s = value; s =
 *          (type)(s + ovalue);
 */
public class NumberConvert {

	static {
		int a = 1;
	}

	/**
	 * @Title: main
	 * @Description: TODO
	 */
	public static void main(String[] args) {
		byte a = (byte) 257;
		byte b = 1;
		byte c = (byte) (a + b);
		System.out.println(c);
		long mills = 1L * 365 * 24 * 60 * 60 * 1000;
		System.out.println(mills);
		short i = 1;
		i += 1;
		i++;
		System.out.println(i);
		if (new Object() {
			{
				System.out.print("Hello,");
			}
		} == null) {
			System.out.print("Hello,");
		} else {
			System.out.println("World");
		}
		int value = Integer.parseInt("00001111101001011111000010101100", 2);// 即value=262533292
		System.out.println(value);

		/**
		 * 1 位运算符
		 * 
		 * 一共3个移位运算符，左移位<<，右移位>>和无符号移位>>>。
		 * 
		 * l 左移位<< 在低位处补0。     val*(2的N次方)
		 * 
		 * l 右移位>> 若值为正则在高位插入0，若值为负则在高位插入1。
		 * 
		 * l 无符号右移位>>> 无论正负都在高位处插入0。
		 * 
		 * 2 位逻辑运算符
		 * 
		 * l & 对两个整型操作数中对应位执行布尔代数，两个位都为1时输出1，否则0。
		 * 
		 * l | 对两个整型操作数中对应位执行布尔代数，两个位都为0时输出0，否则1。
		 * 
		 * l ~ 非运算符
		 * 
		 * l ^ 对两个整型操作数中对应位执行布尔代数，两个位相等0，不等1。
		 */

		int val = 4;
		System.out.println(Integer.toBinaryString(-14));
		System.out.println(Integer.toBinaryString(14));
		System.out.println(Integer.toBinaryString(-2));
		System.out.println(Integer.toBinaryString(2));
		System.out.println(3 & 5);

		int v = -3;
		System.out.println(v << 4); // v*(2的N次方)
		System.out.println(7L >> 65); // 正数左补0，负数左补1，右边丢//（int 32位  long 64位）大于取模  
	}

}
/** Code End */
